﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Security;
using System.Security.Cryptography;

namespace BaseData.Common
{
    /// <summary>
    /// Hash加密类
    /// </summary>
    public class HashEncrypt
    {
        /// <summary>
        /// HashAlgorithm枚举
        /// </summary>
        protected HashAlgorithm mCryptoService;
        /// <summary>
        /// ServiceProviderEnum枚举
        /// </summary>
        protected ServiceProviderEnum mAlgorithm;

        /// <summary>
        /// ServiceProviderEnum枚举
        /// </summary>
        public enum ServiceProviderEnum : int
        {
            /// <summary>
            /// SHA1加密算法
            /// </summary>
            SHA1,
            /// <summary>
            /// SHA256加密算法
            /// </summary>
            SHA256,
            /// <summary>
            /// SHA384加密算法
            /// </summary>
            SHA384,
            /// <summary>
            /// SHA512加密算法
            /// </summary>
            SHA512,
            /// <summary>
            /// MD5加密算法
            /// </summary>
            MD5
        }

        /// <summary>
        /// 缺省的hash算法（SHA1）
        /// </summary>
        public HashEncrypt()
        {
            mCryptoService = new SHA1Managed();
            mAlgorithm = ServiceProviderEnum.SHA1;
        }

        /// <summary>
        /// 利用ServiceProviderEnum来选择一种加密算法
        /// </summary>
        /// <param name="serviceProvider">ServiceProviderEnum枚举</param>
        public HashEncrypt(ServiceProviderEnum serviceProvider)
        {
            //根据ServiceProviderEnum选择一个hash算法
            switch (serviceProvider)
            {
                case ServiceProviderEnum.MD5:
                    mAlgorithm = ServiceProviderEnum.MD5;
                    mCryptoService = new MD5CryptoServiceProvider();
                    break;
                case ServiceProviderEnum.SHA1:
                    mAlgorithm = ServiceProviderEnum.SHA1;
                    mCryptoService = new SHA1Managed();
                    break;
                case ServiceProviderEnum.SHA256:
                    mAlgorithm = ServiceProviderEnum.SHA256;
                    mCryptoService = new SHA256Managed();
                    break;
                case ServiceProviderEnum.SHA384:
                    mAlgorithm = ServiceProviderEnum.SHA384;
                    mCryptoService = new SHA384Managed();
                    break;
                case ServiceProviderEnum.SHA512:
                    mAlgorithm = ServiceProviderEnum.SHA512;
                    mCryptoService = new SHA512Managed();
                    break;
            }
        }

        /// <summary>
        /// 根据hash算法的名字选择hash算法
        /// </summary>
        /// <param name="serviceProviderName">hash算法的名字</param>
        public HashEncrypt(string serviceProviderName)
        {
            try
            {
                //根据hash算法的名字选择hash算法
                switch (serviceProviderName.ToUpper())
                {
                    case "MD5":
                        serviceProviderName = "MD5";
                        mAlgorithm = ServiceProviderEnum.MD5;
                        break;
                    case "SHA1":
                        serviceProviderName = "SHA1";
                        mAlgorithm = ServiceProviderEnum.SHA1;
                        break;
                    case "SHA256":
                        serviceProviderName = "SHA256";
                        mAlgorithm = ServiceProviderEnum.SHA256;
                        break;
                    case "SHA384":
                        serviceProviderName = "SHA384";
                        mAlgorithm = ServiceProviderEnum.SHA384;
                        break;
                    case "SHA512":
                        serviceProviderName = "SHA512";
                        mAlgorithm = ServiceProviderEnum.SHA512;
                        break;
                }
                mCryptoService = (HashAlgorithm)CryptoConfig.CreateFromName(serviceProviderName);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        /// <summary>
        /// hash一个文件
        /// </summary>
        /// <param name="filePath">文件路径</param>
        public string HashFile(string filePath)
        {
            string hashCode = null;

            try
            {
                FileStream fs = System.IO.File.Open(filePath, FileMode.Open, FileAccess.Read);
                byte[] encodedBytes = this.mCryptoService.ComputeHash(fs);
                hashCode = BitConverter.ToString(encodedBytes).Replace("-", "");
                fs.Close();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            return hashCode;
        }

        /// <summary>
        /// hash一个字符串
        /// </summary>
        /// <param name="originalPassword">需要hash的字符串</param>
        /// <returns>hash后的字符串</returns>
        public string HashString(string originalPassword)
        {
            byte[] originalBytes;
            byte[] encodedBytes;
            string hashCode = null;

            try
            {
                originalBytes = System.Text.UTF8Encoding.UTF8.GetBytes(originalPassword);
                encodedBytes = this.mCryptoService.ComputeHash(originalBytes);
                hashCode = BitConverter.ToString(encodedBytes).Replace("-", "");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            return hashCode;
        }
    }
}